<template>
  <div class="custom-query-group">
    <div
      class="group-item"
      v-for="(filterItem, filterItemIndex) in value.filterList"
      :key="filterItem.columnName"
    >
      <!-- 每一个过滤项的逻辑关系 -->
      <div class="item-logic-operator">
        <el-dropdown
          :disabled="filterItemIndex === 0"
          trigger="click"
          @command="value => handlerFilterItemLogicOperatorChange(filterItem, value)"
        >
          <span class="el-dropdown-link">
            {{ LogicOperatorType.getValue(filterItem.logicOperator) }}
            <i v-if="filterItemIndex !== 0" class="el-icon-caret-bottom"></i>
          </span>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item
                v-for="item in LogicOperatorType.getList()"
                :key="item.id"
                :command="item.id"
              >
                <span :class="{ 'el-dropdown-item-active': item.id == value.logicOperator }">
                  {{ item.name }}
                </span>
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
      <!-- 每一个过滤项的内容 -->
      <div class="group-item-content">
        <div class="title">
          <!-- 过滤字段选择 -->
          <el-popover
            placement="bottom-start"
            trigger="click"
            popper-class="custom-query-group-field-select-popper"
          >
            <el-cascader-panel
              :value="[filterItem.tableName, filterItem.columnName]"
              :options="fieldList"
              :props="{
                value: 'id',
                label: 'name',
                children: 'children'
              }"
              @change="val => handlerFiledSelect(filterItem, val)"
            />
            <span slot="reference" style="color: #606266; font-size: 14px; cursor: pointer">
              {{ getFilterItemBindColumnShowName(filterItem) }}
            </span>
          </el-popover>
          <!-- 过滤逻辑选择 -->
          <el-dropdown
            trigger="click"
            style="margin-left: 10px"
            @command="val => handleFilterTypeChange(filterItem, val)"
          >
            <span class="el-dropdown-link">
              {{ CriteriaFilterType.getValue(filterItem.filterType) || '等于' }}
              <i class="el-icon-caret-bottom"></i>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item
                  v-for="item in getValidateFilterTypeList(filterItem)"
                  :key="item.id"
                  :command="item.id"
                  :disabled="item.disabled"
                >
                  <span
                    class="el-dropdown-item-select"
                    :class="{
                      'el-dropdown-item-active': item.id == filterItem.filterType
                    }"
                  >
                    {{ item.name }}
                  </span>
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <div style="width: 100px; flex-grow: 1; flex-shrink: 1" />
          <!-- 过滤项删除 -->
          <div class="rules-tool" @click="deleteFilterItem(filterItem)">
            <i class="el-icon-close"></i>
          </div>
        </div>
        <!-- 过滤值选择 -->
        <div
          class="filter-value-select"
          v-if="
            filterItem.filterType !== CriteriaFilterType.NOT_NULL &&
            filterItem.filterType !== CriteriaFilterType.IS_NULL
          "
        >
          <!-- 字典值类型选择 -->
          <el-select
            v-model="filterItem.valueType"
            :size="defaultFormItemSize"
            style="margin-right: 10px"
          >
            <el-option
              :label="CustomQueryFilterValueType.getValue(CustomQueryFilterValueType.FIXED)"
              :value="CustomQueryFilterValueType.FIXED"
              :disabled="!supportValueTypeFixed(filterItem)"
            />
            <el-option
              :label="CustomQueryFilterValueType.getValue(CustomQueryFilterValueType.DICT)"
              :value="CustomQueryFilterValueType.DICT"
            />
          </el-select>
          <!-- 字典值选择 -->
          <template>
            <!-- 字典值 -->
            <el-cascader
              v-if="filterItem.valueType == CustomQueryFilterValueType.DICT"
              :value="filterItem.filterItemValue"
              :size="defaultFormItemSize"
              popper-class="custom-query-group-casecade-popper"
              style="width: 100%"
              :props="{
                multiple: isMultiSelect(filterItem),
                value: 'id',
                label: 'name',
                checkStrictly: true,
                lazy: true,
                lazyLoad: (node, resolve) => lazyLoadDict(filterItem, node, resolve)
              }"
              clearable
              collapse-tags
              collapse-tags-tooltip
              @input="val => onDictValueChange(filterItem, val)"
            />
            <template v-else>
              <!-- 固定值 -->
              <el-input-number
                v-if="getColumnType(filterItem) === 'Number'"
                v-model="filterItem.filterItemValue"
                :size="defaultFormItemSize"
                style="width: 100%"
                clearable
                placeholder="请输入过滤值"
              />
              <el-date-picker
                v-else-if="getColumnType(filterItem) === 'Date'"
                v-model="filterItem.filterItemValue"
                :size="defaultFormItemSize"
                type="datetime"
                style="width: 100%"
                clearable
                value-format="yyyy-MM-dd HH:mm:ss"
                format="yyyy-MM-dd HH:mm:ss"
                placeholder="请输入过滤值"
              />
              <el-switch
                v-else-if="getColumnType(filterItem) === 'Boolean'"
                v-model="filterItem.filterItemValue"
                style="width: 100%"
                :size="defaultFormItemSize"
              />
              <el-input
                v-else
                v-model="filterItem.filterItemValue"
                :size="defaultFormItemSize"
                style="width: 100%"
                clearable
                placeholder="请输入过滤值"
              />
            </template>
          </template>
        </div>
        <!-- 过滤项工具栏 -->
        <div class="filter-item-tool" v-if="filterItemIndex === value.filterList.length - 1">
          <span class="el-icon-circle-plus-outline" @click="addFilterItem()" />
        </div>
      </div>
    </div>
    <!-- 每个分组之间的过滤逻辑 -->
    <div class="group-logic-operator">
      <el-divider>
        <template>
          <el-dropdown trigger="click" @command="handlerGroupLogicOperatorChange">
            <span class="el-dropdown-link">
              {{ LogicOperatorType.getValue(value.logicOperator) || '且' }}
              <i class="el-icon-caret-bottom"></i>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item
                  v-for="item in LogicOperatorType.getList()"
                  :key="item.id"
                  :command="item.id"
                >
                  <span :class="{ 'el-dropdown-item-active': item.id == value.logicOperator }">
                    {{ item.name }}
                  </span>
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </template>
      </el-divider>
      <div class="group-tool">
        <span class="el-icon-circle-plus-outline" @click="addGroup"></span>
        <span class="el-icon-delete" style="margin-left: 5px" @click="deleteGroup"></span>
      </div>
    </div>
  </div>
</template>

<script>
import { treeDataTranslate, traverseTree } from '@/utils';

export default {
  name: 'CustomQueryGroup',
  props: {
    value: {
      type: Object
    },
    fieldList: {
      type: Array,
      default: () => []
    },
    dictList: {
      type: Array,
      default: () => []
    },
    getDictDataList: {
      type: Function
    }
  },
  methods: {
    supportValueTypeFixed(filterItem) {
      let bindColumn = this.getFilterItemBindColumn(filterItem);
      if (bindColumn == null) return true;
      return (
        filterItem.filterType !== this.CriteriaFilterType.IN &&
        filterItem.filterType !== this.CriteriaFilterType.NOT_IN
      );
    },
    getValidateFilterTypeList(filterItem) {
      let bindColumn = this.getFilterItemBindColumn(filterItem);
      return this.CriteriaFilterType.getList()
        .filter(item => {
          return item.id !== this.CriteriaFilterType.BETWEEN;
        })
        .map(item => {
          let disabled = false;
          if (
            item.id === this.CriteriaFilterType.IN ||
            item.id === this.CriteriaFilterType.NOT_IN
          ) {
            disabled = !(bindColumn && bindColumn.dictInfo);
          }
          return {
            ...item,
            disabled
          };
        });
    },
    getFilterItemBindColumnShowName(filterItem) {
      const bindTable = this.fieldList.find(item => item.id === filterItem.tableName);
      if (bindTable) {
        const bindColumn = bindTable.children.find(item => item.id === filterItem.columnName);
        return bindTable.name + ' / ' + bindColumn.name;
      }
      return 'T 描述';
    },
    getFilterItemBindColumn(filterItem) {
      const bindTable = this.fieldList.find(item => item.id === filterItem.tableName);
      if (bindTable) {
        return bindTable.children.find(item => item.id === filterItem.columnName);
      } else {
        return undefined;
      }
    },
    onDictValueChange(filterItem, val) {
      console.log(filterItem, val);
      if (this.isMultiSelect(filterItem)) {
        filterItem.filterItemValue = (val || []).filter(item => {
          return item.length > 1;
        });
      } else {
        filterItem.filterItemValue = val && val.length > 1 ? val : undefined;
      }
      this.onChange();
    },
    getFilterItemDictList(filterItem) {
      let tempList = [];
      if (filterItem.valueType === this.CustomQueryFilterValueType.DICT) {
        let bindColumn = this.getFilterItemBindColumn(filterItem);
        if (bindColumn && bindColumn.dictInfo) {
          tempList = this.dictList.filter(item => item.id === bindColumn.dictInfo.dictId);
        }
        if (tempList.length <= 0) {
          tempList = this.dictList;
        }
        return tempList;
      }
      return [];
    },
    lazyLoadDict(filterItem, node, resolve) {
      console.log(filterItem, node);
      const parentNode = node.data;
      let childData = parentNode ? parentNode.children : undefined;
      let bindColumn = this.getFilterItemBindColumn(filterItem);
      if (node.level > 1) {
        return resolve([]);
      }
      if (node.level === 0) {
        childData = this.getFilterItemDictList(filterItem);
        childData.children = [];
        return resolve(childData);
      }
      const dictInfo = (bindColumn || {}).dictInfo;
      console.log(node, bindColumn, dictInfo);
      if (this.getDictDataList == null) {
        return resolve([]);
      }
      if (childData) {
        resolve([]);
      } else {
        this.getDictDataList(this, parentNode, {}, false)
          .then(data => {
            if (dictInfo && dictInfo.treeFlag) {
              data = treeDataTranslate(data);
            }
            traverseTree(data, node => {
              node.leaf = !node.children || node.children.length <= 0;
            });
            this.$set(parentNode, 'children', data);
            resolve(data);
          })
          .catch(() => {
            resolve([]);
          });
      }
    },
    isMultiSelect(filterItem) {
      return (
        filterItem.valueType === this.CustomQueryFilterValueType.DICT &&
        (filterItem.filterType === this.CriteriaFilterType.IN ||
          filterItem.filterType === this.CriteriaFilterType.NOT_IN)
      );
    },
    getColumnDataType(objectFieldType) {
      switch (objectFieldType) {
        case 'String':
          return 'String';
        case 'Date':
          return 'Date';
        case 'Boolean':
          return 'Boolean';
        case 'Integer':
        case 'Long':
        case 'Float':
        case 'Double':
        case 'BigDecimal':
          return 'Number';
        default:
          return undefined;
      }
    },
    getColumnType(filterItem) {
      const bindColumn = this.getFilterItemBindColumn(filterItem);
      if (bindColumn) {
        return this.getColumnDataType(bindColumn.objectFieldType);
      } else {
        return 'String';
      }
    },
    handlerFilterItemLogicOperatorChange(filterItem, val) {
      filterItem.logicOperator = val;
      this.value.filterList = [...this.value.filterList];
      this.onChange();
    },
    deleteFilterItem(filterItem) {
      if (this.value.filterList.length === 1) {
        this.value.filterList = [];
        this.addFilterItem();
      } else {
        this.value.filterList = this.value.filterList.filter(item => {
          return item !== filterItem;
        });
      }
      this.onChange();
    },
    addFilterItem() {
      this.value.filterList.push({
        tableName: undefined,
        columnName: undefined,
        valueType: this.CustomQueryFilterValueType.FIXED,
        filterType: this.CriteriaFilterType.EQ,
        logicOperator: this.LogicOperatorType.AND,
        filterItemValue: ''
      });
      this.onChange();
    },
    handlerFiledSelect(filterItem, val) {
      filterItem.tableName = val[0];
      filterItem.columnName = val[1];
      filterItem.filterType = this.CriteriaFilterType.EQ;
      let bindColumn = this.getFilterItemBindColumn(filterItem);
      // Boolean 类型默认值为 false
      if (bindColumn && this.getColumnType(filterItem) === 'Boolean') {
        filterItem.filterItemValue = false;
      } else {
        filterItem.filterItemValue = '';
      }
      // 绑定字段支持字典，则默认值类型为字典
      if (bindColumn && bindColumn.dictInfo) {
        filterItem.valueType = this.CustomQueryFilterValueType.DICT;
      } else {
        filterItem.valueType = this.CustomQueryFilterValueType.FIXED;
      }
      this.onChange();
    },
    handlerGroupLogicOperatorChange(val) {
      this.value.logicOperator = val;
      this.onChange();
    },
    addGroup() {
      this.$emit('add');
    },
    deleteGroup() {
      this.$emit('delete', this.value);
    },
    handleFilterTypeChange(filterItem, val) {
      filterItem.filterType = val;
      let bindColumn = this.getFilterItemBindColumn(filterItem);
      // Boolean 类型默认值为 false
      if (bindColumn && this.getColumnType(filterItem) === 'Boolean') {
        filterItem.filterItemValue = false;
      } else {
        filterItem.filterItemValue = '';
      }
      if (val === this.CriteriaFilterType.IN || val === this.CriteriaFilterType.NOT_IN) {
        filterItem.valueType = this.CustomQueryFilterValueType.DICT;
      } else {
        filterItem.valueType = this.CustomQueryFilterValueType.FIXED;
      }
      this.onChange();
    },
    onChange() {
      this.$emit('input', this.value);
    }
  }
};
</script>

<style scoped>
.custom-query-group {
  display: flex;
  flex-direction: column;
}
.group-item {
  display: flex;
}
.group-item + .group-item {
  margin-top: 10px;
}
.item-logic-operator {
  width: 40px;
  height: 32px;
  line-height: 32px;
  flex-grow: 0;
  flex-shrink: 0;
}
.group-item-content {
  width: 200px;
  flex-grow: 1;
  flex-shrink: 1;
}
.group-item-content .title {
  display: flex;
  align-items: center;
  width: 100%;
  height: 32px;
  line-height: 32px;
  flex-grow: 1;
  flex-shrink: 1;
  margin-bottom: 10px;
}
.filter-value-select {
  display: flex;
  align-items: center;
  width: 100%;
}
.group-logic-operator {
  position: relative;
  width: 100%;
}
.group-tool {
  position: absolute;
  top: 13px;
  right: 0;
  font-size: 16px;
  line-height: 24px;
  border-radius: 24px;
  background: white;
  padding-left: 6px;
}
.group-tool span {
  cursor: pointer;
}
.filter-item-tool {
  height: 32px;
  line-height: 32px;
  font-size: 16px;
  margin-top: 5px;
}
.filter-item-tool span {
  cursor: pointer;
}
.rules-tool {
  width: 24px;
  height: 24px;
  line-height: 24px;
  font-size: 16px;
  text-align: center;
  border-radius: 50%;
  cursor: pointer;
}
.rules-tool:hover {
  background-color: rgba(0, 0, 0, 0.1);
}
.custom-query-group /deep/ .el-dropdown {
  cursor: pointer;
}
</style>

<style>
.custom-query-group-casecade-popper .el-cascader-panel .el-cascader-menu:first-child .el-checkbox {
  display: none;
}
.custom-query-group-casecade-popper .el-cascader-panel .el-cascader-menu:first-child .el-radio {
  display: none;
}
.custom-query-group-field-select-popper {
  padding: 0px;
}
</style>
